import time
from datetime import datetime, timedelta

from flask import request, render_template, current_app, redirect, url_for, session, g, abort, jsonify

from info import db
from info.modules.admin import admin_blue
from info.utils.common import user_login_data, file_upload
from info.utils.constants import ADMIN_USER_PAGE_MAX_COUNT, ADMIN_NEWS_PAGE_MAX_COUNT, QINIU_DOMIN_PREFIX
from info.utils.models import User, News, Category
from info.utils.response_code import RET, error_map


@admin_blue.route('/login', methods=["GET", "POST"])
def login():
    # GET展示页面
    if request.method == "GET":
        # 判断用户是否登陆（session中记录了管理员账号）
        is_admin = session.get("is_admin")
        if is_admin:  # 说明管理员已经登录，重新定位到后台首页
            return redirect(url_for("admin.index"))
        return render_template("admin/login.html")

    # POST 提交数据
    # 获取参数
    username = request.form.get("username")
    password = request.form.get("password")
    # 校验参数
    if not all([username, password]):
        return render_template("admin/login.html", errmsg="参数不足")

    # 查询对应的管理员用户数据
    try:
        user = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except BaseException as e:
        current_app.logger.error(e)
        return render_template("admin/login.html", errmsg="数据库查询失败")

    if not user:
        return render_template("admin/login.html", errmsg="该管理员不存在")

    # 校验账号/密码
    if user.check_passoword(password) == False:
        return render_template("admin/login.html", errmsg="管理员密码错误")

    # 使用session记录管理员
    session["user_id"] = user.id
    session["is_admin"] = True

    # 验证通过，重定向到后台
    return redirect(url_for("admin.index"))


# 退出登录
@admin_blue.route('/logout')
def logout():
    session.pop("user_id", None)
    session.pop("is_admin", None)

    return redirect(url_for("admin.login"))


# 后台页面
@admin_blue.route('/index')
@user_login_data
def index():
    return render_template("admin/index.html", user=g.user.to_dict())


# 数据统计
@admin_blue.route('/user_count')
def user_count():
    # 查询数据库注册用户数据
    totle_count = 0
    try:
        totle_count = User.query.filter(User.is_admin == False).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 月新增注册人数:注册时间>=本月1号0点
    mon_count = 0

    # 获取当前时间的日期组件：年 月
    t = time.localtime()
    # 构建日期字符串 2019-02-01
    mon_date_str = "%d-%02d-01" % (t.tm_year, t.tm_mon)
    # 转换日期对象
    mon_date = datetime.strptime(mon_date_str, "%Y-%m-%d")
    try:
        mon_count = User.query.filter(User.is_admin == False, User.create_time >= mon_date).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 日新增注册人数 注册时间 >=本月本日0点
    day_count = 0

    # 构建日期字符串
    day_date_str = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday)
    # 转换日期对象
    day_date = datetime.strptime(day_date_str, "%Y-%m-%d")
    try:
        day_count = User.query.filter(User.is_admin == False, User.create_time >= day_date).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 某日新增注册人数  注册时间 >= 当日零点 , < 次日零点
    # 获取当日零点 次日零点 的日期对象
    active_count = []  # 记录注册人数
    active_time = []  # 记录注册时间
    for i in range(0, 30):
        begin_date = day_date - timedelta(days=i)
        end_date = begin_date + timedelta(days=1)
        try:
            one_day_count = User.query.filter(User.is_admin == False, User.create_time >= begin_date,
                                              User.create_time < end_date).count()
            # print("*********************")
            # print(one_day_count)
            # 将最近30天的注册人数添加到列表中
            active_count.append(one_day_count)
            # 日期对象转换成日期字符串
            one_day_str = begin_date.strftime("%Y-%m-%d")
            active_time.append(one_day_str)
        except BaseException as e:
            current_app.logger.error(e)

    # 列表反转
    active_count.reverse()
    active_time.reverse()

    data = {
        "totle_count": totle_count,
        "mon_count": mon_count,
        "day_count": day_count,
        "active_count": active_count,
        "active_time": active_time
    }

    return render_template("admin/user_count.html", data=data)


# 用户列表
@admin_blue.route('/user_list')
def user_list():
    # 接收用户信息
    p = request.args.get("p", 1)
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)  # 资源不可用
    # 分页查询所有用户
    try:
        pn = User.query.paginate(p, ADMIN_USER_PAGE_MAX_COUNT)
        # print(pn)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # 类字典结构
    data = {
        "user_list": [user.to_admin_dict() for user in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }
    # 将数据传入模版渲染
    return render_template("admin/user_list.html", data=data)


# 新闻审核列表
@admin_blue.route('/news_review')
def news_review():
    # 接收用户信息
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)  # 资源不可用
    # 分页查询 所有新闻
    # 过滤关键字查询
    filter_list = []
    if keyword:  # 说明有关键字搜索
        filter_list.append(News.title.contains(keyword))
    try:
        pn = News.query.filter(*filter_list).paginate(p, ADMIN_NEWS_PAGE_MAX_COUNT)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # 类字典结构
    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }
    # 将数据传入模版渲染
    return render_template("admin/news_review.html", data=data)


# 新闻审核详情  动态URL获取news_id
@admin_blue.route('/news_review_detail/<int:news_id>')
def news_review_detail(news_id):
    # 通过获取新闻的news_id查询数据库
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)

    return render_template("admin/news_review_detail.html", news=news.to_dict())


# 新闻审核
@admin_blue.route('/news_review_action', methods=["POST"])
def news_review_action():
    # 获取数据
    news_id = request.json.get("news_id")
    action = request.json.get("action")
    reason = request.json.get("reason")

    # 校验数据
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if action not in ("accept", "reject"):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 根据新闻id数据库查询
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    if not news:
        return jsonify(errno=RET.NODATA, errmsg=error_map[RET.NODATA])
    # 数据库行为 修改新闻审核状态
    if action == "accept":
        news.status = 0  # 审核通过
    else:  # 审核未通过
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
        news.reason = reason
        news.status = -1

        # 返回json数据
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 新闻编辑列表 （和新闻审核列表一样）
@admin_blue.route('/news_edit')
def news_edit():
    # 接收用户信息
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)  # 资源不可用
    # 分页查询 所有新闻
    # 过滤关键字查询
    filter_list = []
    if keyword:  # 说明有关键字搜索
        filter_list.append(News.title.contains(keyword))
    try:
        pn = News.query.filter(*filter_list).paginate(p, ADMIN_NEWS_PAGE_MAX_COUNT)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # 类字典结构
    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }
    # 将数据传入模版渲染
    return render_template("admin/news_edit.html", data=data)


# 新闻编辑详情
@admin_blue.route('/news_edit_detail')
def news_edit_detail():
    # 获取参数
    news_id = request.args.get("news_id")
    # 校验参数
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)  # 资源不可用
    # 通过获取新闻的news_id查询数据库
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # 查询所有的分类数据
    try:
        categories = Category.query.filter(Category.id != 1).all()
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # 标识新闻当前对应的分类
    category_list = []
    for category in categories:
        category_dict = category.to_dict()
        is_selected = False  # 记录该分类是否为当前对应的分类

        if category.id == news.category_id:
            is_selected = True

        category_dict["is_selected"] = is_selected
        category_list.append(category_dict)

    return render_template("admin/news_edit_detail.html", news=news.to_dict(), category_list=category_list)


# 提交编辑
@admin_blue.route('/news_edit_detail', methods=["POST"])
def news_edit_detail_post():
    # 获取参数
    news_id = request.form.get("news_id")
    title = request.form.get("title")
    category_id = request.form.get("category_id")
    digest = request.form.get("digest")
    index_image = request.files.get("index_image")
    content = request.form.get("content")
    # 校验参数
    if not all([news_id, title, category_id, digest, content]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        news_id = int(news_id)
        category_id = int(category_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    # 查询数据库
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])
    # 修改编辑 数据库操作
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.content = content
    if index_image:
        try:
            img_bytes = index_image.read()
            print(img_bytes)
            file_name = file_upload(img_bytes)
            print(file_name)
            news.index_image_url = QINIU_DOMIN_PREFIX + file_name
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.THIRDERR, errmsg=error_map[RET.THIRDERR])
    # 返回json
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 新增/修改分类
@admin_blue.route('/news_type', methods=["POST", "GET"])
def news_type():
    if request.method == "GET":
        # 查询数据库 分类
        try:
            categories = Category.query.filter(Category.id != 1).all()
        except BaseException as e:
            current_app.logger.error(e)
            return abort(500)
        return render_template("admin/news_type.html", categories=categories)

    # 获取参数
    name = request.json.get("name")
    id = request.json.get("id")
    # 校验参数
    if not name:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 根据id来判断执行相应的数据库行为
    if id:
        try:
            id = int(id)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
        # 数据库查询
        try:
            category = Category.query.get(id)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

        category.name = name
    else:
        new_category = Category(name=name)
        db.session.add(new_category)
    # 返回json数据
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])
